package com.xc.sys.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.xc.common.object.LayuiTableResponse;
import com.xc.common.object.PageInfo;
import com.xc.common.object.ResponseEntity;
import com.xc.common.object.TreeObject;
import com.xc.common.tool.Helper;
import com.xc.db.tables.SysOrganization;
import com.xc.db.tables.SysUser;
import com.xc.sys.entity.SysDictEntity;
import com.xc.sys.entity.SysOrganizationEntity;
import com.xc.sys.entity.SysUserEntity;
import com.xc.sys.service.SysDictService;
import com.xc.sys.service.SysOrganizationService;
import com.xc.sys.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@CrossOrigin

@RequestMapping({ "/org" })
public class SysOrganizationController {
	@Value("${env.filedir}")
    private String filedir;
	@Autowired
	private DSLContext dsl;
	private SysUser USER = SysUser.SYS_USER.as("USER");
	@Autowired
	private SysOrganizationService sysOrganizationService;
	private SysOrganization ORG = SysOrganization.SYS_ORGANIZATION.as("ORG");
	@SuppressWarnings("unchecked")
	@CrossOrigin(origins = "*", allowedHeaders = {"*"}, methods = {RequestMethod.GET})
	@RequestMapping({ "/getPageList" })
	public LayuiTableResponse<SysOrganizationEntity> getPageList(HttpServletRequest request) {
		SysUserEntity me = Helper.getMe(request);
		if(me==null) {
			String createUserId = request.getParameter("createUserId");
			me = SysUserService.getFrameCaches(createUserId);
		}
		String name = request.getParameter("name");
		String keywords = request.getParameter("keywords");
		if(StringUtils.isNotEmpty(keywords)) {
			name = keywords;
		}
		
		String parentId = request.getParameter("parentId");
		Integer limit = Integer.valueOf(request.getParameter("limit"));
		Integer page = Integer.valueOf(request.getParameter("page"));
		LayuiTableResponse<SysOrganizationEntity> ltr = new LayuiTableResponse<>();
		Condition cond = ORG.STATE.notEqual(-1);
		if (StringUtils.isEmpty(parentId)) {
			cond = cond.and(ORG.PARENT_ID.isNull());
		} else {
			cond = cond.and(DSL.or(ORG.ID.eq(Integer.valueOf(parentId)),ORG.PARENT_ID.eq(Integer.valueOf(parentId))));
		}
		if(StringUtils.isNotEmpty(name)) {
			cond = DSL.or(ORG.NAME.like("%" + name + "%"),ORG.SHORT_NAME.like("%" + name + "%"));
		}
		Long count = this.sysOrganizationService.count(cond);
		PageInfo<SysOrganizationEntity> pageInfo = new PageInfo<>(limit, page);
		ltr.setCount(count);
		this.sysOrganizationService.select(cond, pageInfo,this.ORG.TIER, this.ORG.ORDERNO);
		for(SysOrganizationEntity org : pageInfo.getList()){
			setTxt(org);
		}
		ltr.setData(pageInfo.getList());
		return ltr;
	}
	private void setTxt(SysOrganizationEntity org) {
		SysDictEntity dict = SysDictService.getFromCaches("org-type,"+org.getOrgType());
		if(dict!=null){
			org.setOrgTypeTxt(dict.getName());
		}else {
			org.setOrgTypeTxt("");
		}
	}
	@RequestMapping({ "/getList" })
	public LayuiTableResponse<SysOrganizationEntity> getList(HttpServletRequest request) {
		LayuiTableResponse<SysOrganizationEntity> ltr = new LayuiTableResponse<>();
		Condition cond = ORG.STATE.notEqual(-1);
		String orgType = request.getParameter("orgType");
		
		if (StringUtils.isNotEmpty(orgType)) {
			cond = cond.and(ORG.ORG_TYPE.in(StringUtils.split(orgType,",")));
		} 
		String parentId = request.getParameter("parentId");
		if (StringUtils.isNotEmpty(parentId)) {
			cond = cond.and(ORG.PARENT_ID.in( Lists.newArrayList(StringUtils.split(parentId,",")).stream().map(v->{return Long.valueOf(v);}).collect(Collectors.toList()) ));
		} else {
			if(parentId!=null) {
				cond = cond.and(ORG.PARENT_ID.isNull());
			}
		}
		Long count = sysOrganizationService.count(cond);
		ltr.setCount(count);
		List<SysOrganizationEntity> list = sysOrganizationService.select(cond,ORG.TIER.asc(), ORG.ORDERNO.asc());
		ltr.setData(list);
		return ltr;
	}
	@RequestMapping({ "/getOrgTree" })
	public List<TreeObject> getOrgTree(Integer pid, HttpServletRequest request) {
		List<TreeObject> list = new ArrayList<>();
		joinTreeNode(pid, list, request);
		return list;
	}
	

	@RequestMapping({ "/getFullOrgTree" })
	public List<TreeObject> getFullOrgTree(Integer pid, HttpServletRequest request) {
		List<TreeObject> list = new ArrayList<>();
		joinFullTreeNode(pid, list, request);
		return list;
	}

	/*
	 * 
	 * 功能：选择部门 
	 * 作者：曾平 
	 * 时间：2019年12月14日 上午9:47:06
	 */
	private void joinFullTreeNode(Integer parentId, List<TreeObject> list, HttpServletRequest request) {
		
		Condition cond = ORG.STATE.notEqual(-1);
		String openIds = request.getParameter("openIds");
		if (parentId == null) {
			cond = cond.and(ORG.PARENT_ID.isNull());
		} else {
			cond = cond.and(ORG.PARENT_ID.eq(parentId));
		}
		List<SysOrganizationEntity> result = sysOrganizationService.select(cond, ORG.TIER.asc(), ORG.ORDERNO.asc());
		for (SysOrganizationEntity r : result) {
			String id = r.getId();
			String name = r.getShortName();
			TreeObject treeObject = new TreeObject();
			treeObject.setName(name);
			treeObject.setId(id);
			treeObject.setCode(r.getCode());
			if(StringUtils.isNotEmpty(openIds)) {
				openIds = openIds + ",";
				if(openIds.indexOf(id+",")>-1) {
					treeObject.setOpen(true);
				}
			}
			cond = ORG.PARENT_ID.eq(Integer.valueOf(id));
			List<TreeObject> children = new ArrayList<>();
			List<SysOrganizationEntity> result2 = sysOrganizationService.select(cond, ORG.TIER.asc(),ORG.ORDERNO.asc());
			if (result2.size() != 0) {
				treeObject.setChildren(children);
				treeObject.setIsParent(true);
				joinFullTreeNode(Integer.valueOf(id), children, request);
			}
			list.add(treeObject);
		}
	}

	private void joinTreeNode(Integer parentId, List<TreeObject> list, HttpServletRequest request) {
		Condition cond = ORG.STATE.notEqual(-1);
		SysUserEntity me = Helper.getMe(request);
		if (parentId == null) {
			cond = cond.and(ORG.ID.eq(Integer.valueOf(me.getOrgId())));
		} else {
			cond = cond.and(ORG.PARENT_ID.eq(parentId));
		}
		List<SysOrganizationEntity> result = this.sysOrganizationService.select(cond, ORG.TIER.asc(),ORG.ORDERNO.asc());
		for (SysOrganizationEntity r : result) {
			String id = r.getId();
			String name = r.getShortName();
			TreeObject treeObject = new TreeObject();
			treeObject.setName(name);
			treeObject.setId(id);
			treeObject.setCode(r.getCode());
			cond = this.ORG.PARENT_ID.eq(Integer.valueOf(id));
			List<SysOrganizationEntity> result2 = this.sysOrganizationService.select(cond, this.ORG.TIER.asc(),
					this.ORG.ORDERNO.asc());
			if (result2.size() != 0) {
				treeObject.setIsParent(true);
			}
			list.add(treeObject);
		}
	}
	@RequestMapping({ "/getDTree" }) 
	public JSONObject getDTree(HttpServletRequest request) {
		JSONObject res = new JSONObject(); 
		JSONArray arr = new JSONArray();
		String pid = request.getParameter("pid");
		Integer parentId = null;
		if(StringUtils.isNotEmpty(pid)) {
			parentId = Integer.valueOf(pid);
		}
		res.put("data", arr); 
		JSONObject status = new JSONObject(); 
		status.put("code", 200); 
		status.put("message", "操作成功");
		res.put("status", status); 
		//是否显示数据
		String show = request.getParameter("show");
		if(show!=null&&show.equals("false")){
			return res;
		}
		String self = request.getParameter("self");//如果有这个值，就包含PID自己
		joinDTreeNode(parentId, self, arr, null,request); 
		return res; 
	}
		  
	private void joinDTreeNode(Integer parentId, Object self,JSONArray arr, JSONObject node, HttpServletRequest request) {
		
		String orgType = request.getParameter("orgType");
		Condition cond = ORG.STATE.notEqual(-1);
		String currentId = request.getParameter("currentId");
		if(StringUtils.isNotEmpty(currentId)) {//只查自己
			cond = cond.and(ORG.ID.eq(Integer.valueOf(currentId)));
		}else {
			if (parentId == null) {
				cond = cond.and(ORG.PARENT_ID.isNull());
			} else {
				if(self==null) {
					cond = cond.and(ORG.PARENT_ID.eq(parentId));
				}else {
					cond = cond.and(DSL.or(ORG.ID.eq(parentId)));
					self = null;
					parentId = null;
				}
				
			}
		}
		
		if(StringUtils.isNotEmpty(orgType)) {
			cond = cond.and(ORG.ORG_TYPE.in(StringUtils.split(orgType,",")));
		}
		List<SysOrganizationEntity> result = sysOrganizationService.select(cond, ORG.TIER.asc(), ORG.ORDERNO.asc());
		for(SysOrganizationEntity r : result) { 
			String id = r.getId(); 
			String name = r.getName(); 
			JSONObject treeObject = new JSONObject();
			treeObject.put("title",name); 
			treeObject.put("id",id);
			treeObject.put("parentId",parentId); 
			treeObject.put("checkArr","{\"type\": \"0\", \"checked\": \"0\"}");
			List<SysOrganizationEntity> result2 = sysOrganizationService.select(ORG.PARENT_ID.eq(Integer.valueOf(id))); 
			JSONArray arr2 = new JSONArray(); 
			if(result2.size()>0) { 
				treeObject.put("children", arr2);
				joinDTreeNode(Integer.valueOf(id),self,arr2,treeObject,request); 
			} 
			arr.add(treeObject); 
		} 
	}
	@RequestMapping({ "/countNodes" })
	public long countNodes(HttpServletRequest request) {
		Integer parentId = Integer.valueOf(request.getParameter("parentId"));
		String orgType = request.getParameter("orgType");
		Condition cond = ORG.PARENT_ID.eq(parentId);
		if(StringUtils.isNotEmpty(orgType)) {
			cond = cond.and(ORG.ORG_TYPE.in(StringUtils.split(orgType,",")));
		}
		return sysOrganizationService.count(cond);
	}
	@RequestMapping({ "/refreshNodePersonNum" })
	public ResponseEntity<SysOrganizationEntity> refreshNodePersonNum(HttpServletRequest request) {
		ResponseEntity<SysOrganizationEntity> res = new ResponseEntity<>();
		List<SysOrganizationEntity> list = sysOrganizationService.select(ORG.ID.isNotNull());
		for(SysOrganizationEntity org : list) {
			Integer c = dsl.selectCount().from(USER).where( DSL.or(USER.NODE_ORG_ID.eq(Integer.valueOf(org.getId())),USER.NODE_ORG_ID.in(DSL.select(ORG.ID).from(ORG).where(ORG.CODE.startsWith(org.getCode()+".")))) 
				.and(USER.STATE.eq(1))	).fetchOneInto(Integer.class);
			org.setStaffNum(c);
			sysOrganizationService.update(org);
		}
		return res;
	}

	@RequestMapping({ "/modify" })
	public ResponseEntity<SysOrganizationEntity> modify(SysOrganizationEntity entity) {
		SysOrganizationEntity org = SysOrganizationService.getFromCaches(Integer.valueOf(entity.getId()));
		entity.setCode(org.getCode());
		sysOrganizationService.update(entity);
		SysOrganizationService.orgNameCache.invalidate(org.getName());
		SysOrganizationService.orgNameCache.invalidate(org.getShortName());
		SysOrganizationService.orgCache.invalidate(org.getId());
		ResponseEntity<SysOrganizationEntity> res = new ResponseEntity<>();
		res.setData(entity);
		return res;
	}

	@RequestMapping({ "/save" })
	public ResponseEntity<SysOrganizationEntity> save(SysOrganizationEntity entity) {
		ResponseEntity<SysOrganizationEntity> res = new ResponseEntity<>();
		if (StringUtils.isEmpty(entity.getId())) {
			if(entity.getOrderno()==null) {
				entity.setOrderno(1);
			}
			sysOrganizationService.insert(entity);
		} else {
			if(entity.getParentId()!=null&&!entity.getParentId().isEmpty()) {
				if(entity.getId().equals(entity.getParentId())){
					res.setCode(1);
					res.setMsg("上级机构不能选自己");
					return res;
				}
				SysOrganizationEntity p = SysOrganizationService.getFromCaches(entity.getParentId());
				if(p.getCode().startsWith(entity.getCode())) {
					res.setCode(1);
					res.setMsg("上级机构不能选自己的子节点");
					return res;
				}
			}
			
			sysOrganizationService.update(entity);
			
		}
		
		res.setData(entity);
		return res;
	}

	@RequestMapping({ "/move" })
	@Transactional
	public ResponseEntity<SysOrganizationEntity> move(Integer id, String parentId) {
		ResponseEntity<SysOrganizationEntity> res = new ResponseEntity<>();
		SysOrganizationEntity org = sysOrganizationService.getEntityById(id);
		SysOrganizationService.orgCache.invalidate(id);
		sysOrganizationService.deleteById(id);
		org.setParentId(parentId);
		org.setCode(null);
		sysOrganizationService.insert(org);
		List<SysOrganizationEntity> kids = sysOrganizationService.select(ORG.PARENT_ID.eq(id));
		for (SysOrganizationEntity kid : kids) {
			kid.setCode(null);
			kid.setParentId(org.getId());
			sysOrganizationService.update(kid);
			updateChildren(Integer.valueOf(kid.getId()));
			SysOrganizationService.orgNameCache.invalidate(kid.getName());
			SysOrganizationService.orgNameCache.invalidate(kid.getShortName());
			SysOrganizationService.orgCache.invalidate(kid.getId());
		}
		res.setData(org);
		return res;
	}

	@RequestMapping({ "/moveTop" })
	@Transactional
	public ResponseEntity<SysOrganizationEntity> moveTop(Integer id) {
		ResponseEntity<SysOrganizationEntity> res = new ResponseEntity<>();
		SysOrganizationEntity org = sysOrganizationService.getEntityById(id);
		SysOrganizationService.orgCache.invalidate(id);
		sysOrganizationService.deleteById(id);
		org.setParentId(null);
		org.setCode(null);
		sysOrganizationService.insert(org);
		List<SysOrganizationEntity> kids = sysOrganizationService.select(ORG.PARENT_ID.eq(id));
		for (SysOrganizationEntity kid : kids) {
			kid.setCode(null);
			kid.setParentId(org.getId());
			sysOrganizationService.update(kid);
			SysOrganizationService.orgNameCache.invalidate(kid.getName());
			SysOrganizationService.orgNameCache.invalidate(kid.getShortName());
			SysOrganizationService.orgCache.invalidate(kid.getId());
			updateChildren(Integer.valueOf(kid.getId()));
		}
		res.setData(org);
		return res;
	}
	@RequestMapping("/uploadLogo")
	@Transactional
	public ResponseEntity<Map<String,String>> uploadLogo(HttpServletRequest request,ServletResponse response) throws IOException{
		String orgId = request.getParameter("orgId");
		ResponseEntity<Map<String,String>> res = new ResponseEntity<>();
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;   
		MultipartFile uploadFile = multipartRequest.getFile("file");
		String ordinalFileName = uploadFile.getOriginalFilename();
		String sufix = Helper.getSuffix(ordinalFileName);
		String fileName = orgId + "." + sufix;
		try {
			if(uploadFile.getSize()>0){
				String filePath = filedir + "logo" + File.separator+fileName;
				File destFile = new File(filePath);
				uploadFile.transferTo(destFile);
				SysOrganizationEntity orgEntity = sysOrganizationService.getEntityById(Integer.valueOf(orgId));
				orgEntity.setLogoUrl("logo"+ File.separator + fileName);
				sysOrganizationService.update(orgEntity);
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		Map<String,String> data = new HashMap<>();
		data.put("src", "logo" + File.separator +fileName);
		res.setData(data);
		return res;
	}
	private void updateChildren(Integer parentId) {
		List<SysOrganizationEntity> list = sysOrganizationService.select(ORG.PARENT_ID.eq(parentId), ORG.TIER.asc());
		for (SysOrganizationEntity kid : list) {
			kid.setCode(null);
			sysOrganizationService.update(kid);
			SysOrganizationService.orgNameCache.invalidate(kid.getName());
			SysOrganizationService.orgNameCache.invalidate(kid.getShortName());
			SysOrganizationService.orgCache.invalidate(kid.getId());
			List<SysOrganizationEntity> list2 = sysOrganizationService.select(ORG.PARENT_ID.eq(Integer.valueOf(kid.getId())),ORG.TIER.asc());
			if (list2.size() > 0) {
				updateChildren(Integer.valueOf(kid.getId()));
			}
		}
	}

	@RequestMapping({ "/add" })
	public LayuiTableResponse<SysOrganizationEntity> add(SysOrganizationEntity entity) {
		this.sysOrganizationService.insert(entity);
		LayuiTableResponse<SysOrganizationEntity> ltr = new LayuiTableResponse<>();
		return ltr;
	}

	@RequestMapping({ "/delete" })
	public LayuiTableResponse<SysOrganizationEntity> delete(@RequestBody Map<String,String> params) {
		String ids = params.get("ids");
		Integer[] idarr = Helper.str2integerArr(ids);
		LayuiTableResponse<SysOrganizationEntity> ltr = new LayuiTableResponse<>();
		for (Integer id : idarr) {
			Condition cond = ORG.PARENT_ID.eq(id).and(ORG.STATE.notEqual(-1));
			List<SysOrganizationEntity> list = sysOrganizationService.select(cond);
			if (list.size() == 0) {
				SysOrganizationEntity org = SysOrganizationService.getFromCaches(id);
				org.setState(-1);
				sysOrganizationService.update(org);
			}
		}
		return ltr;
	}

	@RequestMapping({ "/getMySubStores" })
	public LayuiTableResponse<SysOrganizationEntity> getMySubStores(HttpServletRequest request) {
		LayuiTableResponse<SysOrganizationEntity> ltr = new LayuiTableResponse<>();
		SysUserEntity me = Helper.getMe(request);
		SysOrganizationEntity mystore = SysOrganizationService.getFromCaches(Integer.valueOf(me.getOrgId()));
		Condition cond = ORG.CODE.like(mystore.getCode() + "%");
		List<SysOrganizationEntity> list = sysOrganizationService.select(cond, ORG.ORDERNO.asc());
		ltr.setData(list);
		return ltr;
	}

	@RequestMapping({ "/getById" })
	public SysOrganizationEntity getById(Integer id) {
		SysOrganizationEntity org = this.sysOrganizationService.getEntityById(id);
		setTxt(org);
		return org;
	}
	@SuppressWarnings("static-access")
	@RequestMapping({ "/getBranchByOrgId" })
	public SysOrganizationEntity getBranchByOrgId(Integer id) {
		SysOrganizationEntity org = SysOrganizationService.getFromCaches(id);
		for(int i=0;i<6;i++){
			org = sysOrganizationService.getFromCaches(Integer.valueOf(org.getParentId()));
			if(org.getOrgType().equals("branch")){
				break;
			}
		}
		return org;
	}

	@RequestMapping({ "/getByCode" })
	public SysOrganizationEntity getByCode(String code) {
		List<SysOrganizationEntity> orgs = sysOrganizationService.select(ORG.CODE.eq(code));
		if (orgs.size() == 0) {
			return null;
		}
		return orgs.get(0);
	}

	@RequestMapping({ "/getOrgByStoreId" })
	public SysOrganizationEntity getOrgByStoreId(Integer storeId) {
		SysOrganizationEntity org = sysOrganizationService.getTopOrg(storeId);
		return org;
	}

	/**
	 * 根据子叶节点获取最顶层组织树信息
	 * @Date 2020-08-03
	 * @author 黄顺
	 * @return
	 */
	@GetMapping("getTopOrgByChildId/{childId}")
	public  LayuiTableResponse<SysOrganizationEntity> getTopOrgByChildId(@PathVariable("childId")String childId){
		LayuiTableResponse<SysOrganizationEntity> ltr = new LayuiTableResponse<>();
		//获取所有树结构信息
		List<SysOrganizationEntity> list = sysOrganizationService.select(null);
		List<SysOrganizationEntity> sysOrganizationEntityList=new ArrayList<>();
		List<SysOrganizationEntity> sysOrganizationEntityList2=new ArrayList<>();
		getTopOrg(childId, list,sysOrganizationEntityList,sysOrganizationEntityList2);
		ltr.setData(sysOrganizationEntityList);
		ltr.setData2(sysOrganizationEntityList2);
		return ltr;
	}
	public void getTopOrg(String childId,List<SysOrganizationEntity> list,List<SysOrganizationEntity> sysOrganizationEntityList,List<SysOrganizationEntity> sysOrganizationEntityList2){
		for (SysOrganizationEntity organizationEntity:list){
			//得到当前子叶节点信息
			if(childId.equals(organizationEntity.getId())){
				sysOrganizationEntityList2.add(organizationEntity);
				//如果为最顶层节点时则返回当前最顶层信息
				if(organizationEntity.getTier()==1){
					sysOrganizationEntityList.add(organizationEntity);
				}
				else{
					//根据当前子叶节点信息获取上层节点id进行递归
					getTopOrg(organizationEntity.getParentId(), list,sysOrganizationEntityList,sysOrganizationEntityList2);
				}
			}
		}
	}

}
